package com.lwl.blue.seven.test7;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lwl.blue.commont.base.JsonResult;
import com.lwl.blue.commont.base.PageParam;
import com.lwl.blue.commont.base.PageResult;
import com.lwl.blue.seven.constants.ContractStatus;
import com.lwl.blue.seven.controller.Contract7Controller;
import com.lwl.blue.seven.dto.*;
import com.lwl.blue.seven.service.Contract7Service;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * 合同控制器测试类
 * 用于测试Contract7Controller中的各个接口方法
 */
@ExtendWith(MockitoExtension.class)
//@SpringBootTest
public class Contract7ControllerTest {

    // MockMvc用于模拟HTTP请求
    private MockMvc mockMvc;

    // 模拟Contract7Service服务层
    @Mock
    private Contract7Service contract7Service;

    // 注入被测试的Controller，并将@Mock标记的依赖注入其中
    @InjectMocks
    private Contract7Controller contract7Controller;

    // JSON对象映射器，用于序列化和反序列化JSON数据
    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 测试前初始化MockMvc
     */
    @BeforeEach
    public void setUp() {
        mockMvc = MockMvcBuilders.standaloneSetup(contract7Controller).build();
    }

    /**
     * 测试创建合同接口
     * 验证POST /contract7/create接口是否正常工作
     */
    @Test
    public void testCreateContract() throws Exception {
        // 准备测试数据
        Contract7CreateDTO createDTO = new Contract7CreateDTO();
        createDTO.setContractNumber("HT2025001");
        createDTO.setContractName("测试合同");
        createDTO.setSupplierId(1);
        createDTO.setTransactionType("采购");

        List<Contract7CreateItemDTO> itemList = new ArrayList<>();
        Contract7CreateItemDTO itemDTO = new Contract7CreateItemDTO();
        itemDTO.setProductId(1L);
        itemDTO.setProductName("测试商品");
        itemDTO.setProductUnit("件");
        itemDTO.setProductPrice(new BigDecimal("100.0000"));
        itemDTO.setProductQuantity(new BigDecimal("10.0000"));
        itemList.add(itemDTO);
        createDTO.setItemList(itemList);

        JsonResult<Long> result = new JsonResult<>();
        result.success(1L);

        // Mock服务方法
        when(contract7Service.createContract(any(Contract7CreateDTO.class), anyLong())).thenReturn(result);

        // 执行测试
        mockMvc.perform(post("/contract7/create")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(createDTO)))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
    }

    /**
     * 测试查询合同列表接口
     * 验证POST /contract7/list接口是否正常工作
     */
    @Test
    public void testQueryContractList() throws Exception {
        // 准备测试数据
        PageParam<Contract7QueryDTO> pageParam = new PageParam<>();
        pageParam.setPageNum(1);
        pageParam.setPageSize(10);

        // 模拟返回结果
        List<Contract7ListVO> voList = new ArrayList<>();
        Contract7ListVO vo = new Contract7ListVO();
        vo.setContractId(1L);
        vo.setContractNumber("CON-001");
        voList.add(vo);

        PageResult<Contract7ListVO> pageResult = new PageResult<>();
        pageResult.setCount(1L);
        pageResult.setData(voList);

        // 模拟服务层返回
        when(contract7Service.queryContractList(any(PageParam.class), any(Long.class)))
                .thenReturn(pageResult);

        // 创建模拟的请求上下文
        MockHttpServletRequest request = new MockHttpServletRequest();
        RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));

        try {
            mockMvc.perform(post("/contract7/list")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(objectMapper.writeValueAsString(pageParam)))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType(MediaType.APPLICATION_JSON));
        } finally {
            // 清理请求上下文
            RequestContextHolder.resetRequestAttributes();
        }
    }

    /**
     * 测试获取合同详情接口
     * 验证GET /contract7/{contractId}接口是否正常工作
     */
    @Test
    public void testGetContractDetail() throws Exception {
        // 准备测试数据
        Contract7DetailDTO detailDTO = new Contract7DetailDTO();
        detailDTO.setContractId(1L);
        detailDTO.setContractNumber("HT2025001");
        detailDTO.setContractName("测试合同");
        detailDTO.setStatus(ContractStatus.DRAFT.getCode());
        detailDTO.setStatusName(ContractStatus.DRAFT.getName());

        List<Contract7DetailItemDTO> itemList = new ArrayList<>();
        Contract7DetailItemDTO itemDTO = new Contract7DetailItemDTO();
        itemDTO.setDetailId(1L);
        itemDTO.setContractId(1L);
        itemDTO.setProductName("测试商品");
        itemList.add(itemDTO);
        detailDTO.setItemList(itemList);

        JsonResult<Contract7DetailDTO> result = new JsonResult<>();
        result.success(detailDTO);

        // Mock服务方法
        when(contract7Service.getContractDetail(anyLong(), anyLong())).thenReturn(detailDTO);

        // 执行测试
        mockMvc.perform(get("/contract7/{contractId}", 1L))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
    }

    /**
     * 测试更新合同接口
     * 验证PUT /contract7/{contractId}接口是否正常工作
     */
    @Test
    public void testUpdateContract() throws Exception {
        // 准备测试数据
        Contract7CreateDTO updateDTO = new Contract7CreateDTO();
        updateDTO.setContractNumber("HT2025001");
        updateDTO.setContractName("更新后的测试合同");
        updateDTO.setSupplierId(1);
        updateDTO.setTransactionType("采购");

        List<Contract7CreateItemDTO> itemList = new ArrayList<>();
        Contract7CreateItemDTO itemDTO = new Contract7CreateItemDTO();
        itemDTO.setProductId(1L);
        itemDTO.setProductName("测试商品");
        itemDTO.setProductUnit("件");
        itemDTO.setProductPrice(new BigDecimal("100.0000"));
        itemDTO.setProductQuantity(new BigDecimal("10.0000"));
        itemList.add(itemDTO);
        updateDTO.setItemList(itemList);

        JsonResult<Void> result = new JsonResult<>();
        result.success("ok");

        // Mock服务方法
        when(contract7Service.updateContract(anyLong(), any(Contract7CreateDTO.class), anyLong())).thenReturn(result);

        // 执行测试
        mockMvc.perform(put("/contract7/{contractId}", 1L)
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(updateDTO)))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
    }

    /**
     * 测试删除合同接口
     * 验证DELETE /contract7/{contractId}接口是否正常工作
     */
    @Test
    public void testDeleteContract() throws Exception {
        // 准备测试数据
        JsonResult<Void> result = new JsonResult<>();
        result.success("ok");

        // Mock服务方法
        when(contract7Service.deleteContract(anyLong(), anyLong())).thenReturn(result);

        // 执行测试
        mockMvc.perform(delete("/contract7/{contractId}", 1L))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
    }

    /**
     * 测试批量删除合同接口
     * 验证DELETE /contract7/batch接口是否正常工作
     */
    @Test
    public void testBatchDeleteContract() throws Exception {
        // 准备测试数据
        List<Long> contractIds = new ArrayList<>();
        contractIds.add(1L);
        contractIds.add(2L);

        JsonResult<Void> result = new JsonResult<>();
        result.success("成功删除 2 个合同");

        // Mock服务方法
        when(contract7Service.batchDeleteContract(anyList(), anyLong())).thenReturn(result);

        // 执行测试
        mockMvc.perform(delete("/contract7/batch")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(contractIds)))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
    }

    /**
     * 测试提交合同接口
     * 验证POST /contract7/{contractId}/submit接口是否正常工作
     */
    @Test
    public void testSubmitContract() throws Exception {
        // 准备测试数据
        JsonResult<Void> result = new JsonResult<>();
        result.success("提交成功");

        // Mock服务方法
        when(contract7Service.submitContract(anyLong(), anyLong())).thenReturn(result);

        // 执行测试
        mockMvc.perform(post("/contract7/{contractId}/submit", 1L))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
    }

    /**
     * 测试审核通过合同接口
     * 验证POST /contract7/{contractId}/approve接口是否正常工作
     */
    @Test
    public void testApproveContract() throws Exception {
        // 准备测试数据
        JsonResult<Void> result = new JsonResult<>();
        result.success("审核通过");

        // Mock服务方法
        when(contract7Service.approveContract(anyLong(), anyLong())).thenReturn(result);

        // 执行测试
        mockMvc.perform(post("/contract7/{contractId}/approve", 1L))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
    }

    /**
     * 测试驳回合同接口
     * 验证POST /contract7/{contractId}/reject接口是否正常工作
     */
    @Test
    public void testRejectContract() throws Exception {
        // 准备测试数据
        JsonResult<Void> result = new JsonResult<>();
        result.success("已驳回");

        // Mock服务方法
        when(contract7Service.rejectContract(anyLong(), anyLong(), anyString())).thenReturn(result);

        // 执行测试
        mockMvc.perform(post("/contract7/{contractId}/reject", 1L)
                .param("rejectReason", "测试驳回原因"))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
    }

    /**
     * 测试获取合同状态列表接口
     * 验证GET /contract7/status-list接口是否正常工作
     */
    @Test
    public void testGetStatusList() throws Exception {
        // 执行测试
        mockMvc.perform(get("/contract7/status-list"))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
    }

    /**
     * 测试获取合同明细项接口
     * 验证GET /contract7/{contractId}/items接口是否正常工作
     */
    @Test
    public void testGetContractItems() throws Exception {
        // 准备测试数据
        List<Contract7DetailItemDTO> itemList = new ArrayList<>();
        Contract7DetailItemDTO itemDTO = new Contract7DetailItemDTO();
        itemDTO.setDetailId(1L);
        itemDTO.setContractId(1L);
        itemDTO.setProductName("测试商品");
        itemList.add(itemDTO);

        JsonResult<List<Contract7DetailItemDTO>> result = new JsonResult<>();
        result.success(itemList);

        // Mock服务方法
        when(contract7Service.getContractItems(anyLong())).thenReturn(itemList);

        // 执行测试
        mockMvc.perform(get("/contract7/{contractId}/items", 1L))
                .andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON));
    }
}
